package au.edu.jcu.haldbus.examples;

import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.freedesktop.DBus.Introspectable;
import org.freedesktop.Hal.Device;
import org.freedesktop.Hal.Manager;
import org.freedesktop.dbus.DBusConnection;
import org.freedesktop.dbus.DBusSigHandler;
import org.freedesktop.dbus.Variant;
import org.freedesktop.dbus.exceptions.DBusException;

public class TestListenerDeviceAdded implements DBusSigHandler<Manager.DeviceAdded> {

  public static void main(String[] args) {
    DBusConnection conn = null;
    System.out.println("Creating DBus Connection");

    try {
      conn = DBusConnection.getConnection(DBusConnection.SYSTEM);
    } catch (DBusException DBe) {
      System.out.println("Could not connect to bus: " + DBe);
      System.exit(1);
    }

    Manager HAL = null;
    try {
      HAL = conn.getRemoteObject("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager", Manager.class);
      System.out.println("UDIs of all existing objects:");
      String UDI[] = HAL.GetAllDevices();
      for (String element : UDI) {
        System.out.println("   " + element);
      }
      System.out.println("\n\n");

      Introspectable introspectable;
      try {
        introspectable = conn.getRemoteObject("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager", Introspectable.class);

        System.out.println(introspectable.Introspect() + "\n");
      } catch (DBusException e) {
        e.printStackTrace();
      }

      conn.addSigHandler(Manager.DeviceAdded.class, new TestListenerDeviceAdded(conn));
      conn.addSigHandler(Manager.DeviceRemoved.class, new TestListenerDeviceRemoved(conn));

    } catch (DBusException DBe) {
      System.out.println("Could not connect to HAL: " + DBe);
      conn.disconnect();
      System.exit(1);
    } catch (Exception e) {
      e.printStackTrace();
      conn.disconnect();
      System.exit(1);
    }

    try {
      Thread.sleep(1000 * 1000);
    } catch (InterruptedException ex) {
      Logger.getLogger(TestListenerDeviceAdded.class.getName()).log(Level.SEVERE, null, ex);
    }

    // } catch (IOException e) {
    // TODO Auto-generated catch block
    // e.printStackTrace();
    // }
    conn.disconnect();
    System.out.println("DBus hooking complete");

  }

  private DBusConnection conn = null;

  public TestListenerDeviceAdded(DBusConnection c) {
    conn = c;
    System.out.println("TestListenerDeviceAdded added");
  }

  public void dumpProperties(String udi) {
    String str;
    Object o = null;

    Device d;
    // System.out.println("------------------------------------------------------------");
    System.out.println("Properties dump on device '" + udi + "'");

    try {
      d = conn.getRemoteObject("org.freedesktop.Hal", udi, Device.class);
    } catch (DBusException e) {
      e.printStackTrace();
      return;
    }
    Map<String, Variant<Object>> mp = d.GetAllProperties();
    Iterator<String> iter = mp.keySet().iterator();
    while (iter.hasNext()) {
      str = iter.next();
      o = mp.get(str).getValue();
      // System.out.print("Property: " + str + "- type:" +
      // o.getClass().getName());
      System.out.print(String.format("  %-30s : %-55s", str, o instanceof String ? (String) o : o.toString()));
      System.out.println();
    }
  }

  public synchronized void handle(Manager.DeviceAdded s) {
    // System.out.println("SIGNAL!!");
    System.out.println("Manager.DeviceAdded [" + s.obj + "] for [" + s.udiAdded + "]");
    // introspect(s.udiAdded);
    dumpProperties(s.udiAdded);
    System.out.println("\n");
  }

  public void introspect(String udi) {
    Introspectable introspectable;
    try {
      introspectable = conn.getRemoteObject("org.freedesktop.Hal", udi, Introspectable.class);
      // System.out.println("------------------------------------------------------------");
      System.out.println("Introspect on device [" + udi + "]");
      System.out.println(introspectable.Introspect());
    } catch (DBusException e) {
      e.printStackTrace();
    }
  }
}
